#include "util.h"

#include <stdarg.h>
#include <stdio.h>
#include <string.h>

#include <mutex>
#include <sstream>
#include <thread>

static std::mutex logMutex;

void log(const LogLevel level, const char* fileName, const int line, const char* format, ...)
{
    std::lock_guard<std::mutex> lock(logMutex);

    FILE* stream = (level == LOG_ERROR) ? stderr : stdout;

    std::thread::id id = std::this_thread::get_id();
    std::ostringstream oss;
    oss << "[" << id << "]";
    oss << "[file: " << fileName << "]";
    oss << "[line: " << line << "]";
    std::string str = oss.str();

    // 添加日志级别标签
    const char* logTag = "";
    switch (level)
    {
        case LOG_DEBUG:
            logTag = "[DEBUG]";
            break;
        case LOG_INFO:
            logTag = "[INFO]";
            break;
        case LOG_WARNING:
            logTag = "[WARN]";
            break;
        case LOG_ERROR:
            logTag = "[ERROR]";
            break;
        default:
            logTag = "[UNKNOWN]";
            break;
    }

    str += logTag;
    fprintf(stream, "%s", str.c_str());

    va_list args;
    va_start(args, format);
    vfprintf(stream, format, args);
    va_end(args);
}

// 向上取整保证size是alignment的倍数,
// 一是为了简化处理逻辑，另外aligned_alloc必须是对齐参数的倍数，否则编译错误
size_t alignUp(const size_t size, const size_t alignmentSize)
{
    return (size + alignmentSize - 1) / alignmentSize * alignmentSize;
}